package com.xiaoshuidi.cloud.module.rooms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.contract.api.ContractApi;
import com.xiaoshuidi.cloud.module.contract.vo.ContractRoomReqVO;
import com.xiaoshuidi.cloud.module.iot.api.device.DeviceApi;
import com.xiaoshuidi.cloud.module.iot.api.device.vo.*;
import com.xiaoshuidi.cloud.module.iot.common.ResultModel;
import com.xiaoshuidi.cloud.module.rooms.controller.app.device.vo.*;
import com.xiaoshuidi.cloud.module.rooms.enums.DeviceTypeEnum;
import com.xiaoshuidi.cloud.module.rooms.enums.ErrorCodeConstants;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomHouse;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomSdiotDeviceMapping;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomHouseRepository;
import com.xiaoshuidi.cloud.module.rooms.service.AppDeviceService;
import com.xiaoshuidi.cloud.module.rooms.service.RoomHouseService;
import com.xiaoshuidi.cloud.module.rooms.service.RoomSdiotDeviceMappingService;
import com.xiaoshuidi.cloud.module.rooms.vo.RoomHouseRespVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class AppDeviceServiceImpl implements AppDeviceService {

    private final DeviceApi deviceApi;

    private final ContractApi contractApi;

    private final RoomHouseService roomHouseService;

    private final RoomSdiotDeviceMappingService roomSdiotDeviceMappingService;

    private final RoomHouseRepository roomHouseRepository;


    @Override
    public List<AmmeterInfoVO> findAmmeterInfo() {

        List<AmmeterInfoVO> voList = new ArrayList<>();

        Set<Long> roomHouseIdList = doorLockGetRoomId();
        for (Long roomHouseId : roomHouseIdList) {
//            Long roomHouseId = new Long(1667117417873330176l);
            List<RoomSdiotDeviceMapping> roomSdiotDeviceMappings = roomSdiotDeviceMappingService.getDeviceListByRoomId(roomHouseId);
            for (RoomSdiotDeviceMapping roomSdiotDeviceMapping : roomSdiotDeviceMappings) {
                if (DeviceTypeEnum.AMMETER.getName().equals(roomSdiotDeviceMapping.getDeviceType())) {
                    String deviceNo = roomSdiotDeviceMapping.getDeviceNo();
                    AmmeterInfoReq ammeterInfoReq = new AmmeterInfoReq();
                    ammeterInfoReq.setDeviceNo(deviceNo);
                    ResultModel<AmmeterInfoRes> ammeterInfo = deviceApi.getAmmeterInfo(ammeterInfoReq);
                    AmmeterInfoRes data = ammeterInfo.getData();
                    AmmeterInfoVO ammeterInfoVO = new AmmeterInfoVO();
                    ammeterInfoVO.setPayment(data.getPayment());
                    ammeterInfoVO.setCurrentReading(data.getCurrentReading());
                    ammeterInfoVO.setReportTime(data.getReportTime());
                    RoomHouseRespVo roomHouseRespVo = roomHouseService.getRoomHouseinfoById(roomHouseId).getData();
                    ammeterInfoVO.setRoomName(roomHouseRespVo.getFullRoomName());
                    ammeterInfoVO.setDeviceNo(deviceNo);
                    voList.add(ammeterInfoVO);
                }
            }

        }

        return voList;
    }

    @Override
    public AmmeterReportRes getAmmeterReport(WaterMeterReportRequest ammeterReportReqVO) {
        log.info("电表明细入参########## {}", JsonUtils.toJsonString(ammeterReportReqVO));
        String deviceNo = ammeterReportReqVO.getDeviceNo();
        Long queryBeginTime = ammeterReportReqVO.getQueryBeginTime();
        Long queryEndTime = ammeterReportReqVO.getQueryEndTime();
        if (ObjectUtil.isEmpty(queryBeginTime) || queryBeginTime == 0) {
            LocalDateTime currentTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
            LocalDateTime previousMonthTime = currentTime.minusMonths(1);
            queryBeginTime = previousMonthTime.toEpochSecond(ZoneOffset.UTC) * 1000;
            ammeterReportReqVO.setQueryBeginTime(queryBeginTime);
        }
        if (ObjectUtil.isEmpty(queryEndTime) || queryEndTime == 0) {
            LocalDateTime currentTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
            queryEndTime = currentTime.toEpochSecond(ZoneOffset.UTC) * 1000;
            ammeterReportReqVO.setQueryEndTime(queryEndTime);
        }
        Instant instant = Instant.ofEpochMilli(queryBeginTime);
        LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
        ContractTimeVO contractStartAndEndTime = getContractStartAndEndTime(deviceNo);
        if(ObjectUtil.isNotEmpty(contractStartAndEndTime)){
            LocalDate contractStartTime = contractStartAndEndTime.getStartTime();
            if (ObjectUtil.isNotEmpty(contractStartTime)) {
                int comparison = localDate.compareTo(contractStartTime);
                ZonedDateTime zonedDateTime = contractStartTime.atStartOfDay(ZoneId.systemDefault());
                long startTime = zonedDateTime.toInstant().toEpochMilli();
                if (comparison < 0) {
                    ammeterReportReqVO.setQueryBeginTime(startTime);
                }
            }
        }
        log.info("远程调用iot电表明细入参########## {}", JsonUtils.toJsonString(ammeterReportReqVO));
        ResultModel<AmmeterReportRes> ammeterReport = deviceApi.getAmmeterReport(ammeterReportReqVO);
        return ammeterReport.getData();
    }

    @Override
    public List<WaterMeterVO> getWatermeterInfo() {

        List<WaterMeterVO> waterMeterVOList = new ArrayList<>();
        Set<Long> roomHouseIdList = doorLockGetRoomId();
        for (Long roomHouseId : roomHouseIdList) {
            WaterMeterVO waterMeterVO = new WaterMeterVO();
            List<WaterMeterInfoVO> voList = new ArrayList<>();
//        Long roomHouseId = new Long(1670679850211979264l);
            List<RoomSdiotDeviceMapping> roomSdiotDeviceMappings = roomSdiotDeviceMappingService.getDeviceListByRoomId(roomHouseId);
            for (RoomSdiotDeviceMapping roomSdiotDeviceMapping : roomSdiotDeviceMappings) {
                if (DeviceTypeEnum.COLDWATER.getName().equals(roomSdiotDeviceMapping.getDeviceType()) || DeviceTypeEnum.HOTWATER.getName().equals(roomSdiotDeviceMapping.getDeviceType())) {
                    String deviceNo = roomSdiotDeviceMapping.getDeviceNo();
                    WaterMeterCommonRequest waterMeterCommonRequest = new WaterMeterCommonRequest();
                    waterMeterCommonRequest.setDeviceNo(deviceNo);
                    ResultModel<WaterMeterCommonResponse> watermeterInfo = deviceApi.getWatermeterInfo(waterMeterCommonRequest);
                    WaterMeterCommonResponse response = watermeterInfo.getData();
                    WaterMeterInfoVO waterMeterInfoVO = new WaterMeterInfoVO();
                    waterMeterInfoVO.setDeviceNo(deviceNo);
                    waterMeterInfoVO.setDeviceType(response.getDeviceType());
                    waterMeterInfoVO.setPayment(response.getPayment());
                    waterMeterInfoVO.setCurrentReading(response.getCurrentReading());
                    waterMeterInfoVO.setReportTime(response.getReportTime());
                    RoomHouseRespVo roomHouseRespVo = roomHouseService.getRoomHouseinfoById(roomHouseId).getData();
                    waterMeterInfoVO.setRoomName(roomHouseRespVo.getFullRoomName());
                    waterMeterInfoVO.setRoomHouseId(roomHouseId);
                    voList.add(waterMeterInfoVO);
                    waterMeterVO.setList(voList);
                    waterMeterVO.setRoomHouseId(roomHouseId);
                }

            }
            waterMeterVOList.add(waterMeterVO);
        }
        List<WaterMeterVO> filteredList = waterMeterVOList.stream()
                .filter(vo -> vo.getRoomHouseId() != null && vo.getList() != null)
                .collect(Collectors.toList());
        return filteredList;
    }

    @Override
    public WaterMeterReportResponse getWatermeterReport(WaterMeterReportRequest waterMeterReportRequestModel) {
        log.info("水表明细入参########## {}", JsonUtils.toJsonString(waterMeterReportRequestModel));
        String deviceNo = waterMeterReportRequestModel.getDeviceNo();
        Long queryBeginTime = waterMeterReportRequestModel.getQueryBeginTime();
        Long queryEndTime = waterMeterReportRequestModel.getQueryEndTime();
        if (ObjectUtil.isEmpty(queryBeginTime) || queryBeginTime == 0) {
            LocalDateTime currentTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
            LocalDateTime previousMonthTime = currentTime.minusMonths(1);
            queryBeginTime = previousMonthTime.toEpochSecond(ZoneOffset.UTC) * 1000;
            waterMeterReportRequestModel.setQueryBeginTime(queryBeginTime);
        }
        if (ObjectUtil.isEmpty(queryEndTime) || queryEndTime == 0) {
            LocalDateTime currentTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
            queryEndTime = currentTime.toEpochSecond(ZoneOffset.UTC) * 1000;
            waterMeterReportRequestModel.setQueryEndTime(queryEndTime);
        }
        Instant instant = Instant.ofEpochMilli(queryBeginTime);
        LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
        ContractTimeVO contractStartAndEndTime = getContractStartAndEndTime(deviceNo);
        if(ObjectUtil.isNotEmpty(contractStartAndEndTime)){
            LocalDate contractStartTime = contractStartAndEndTime.getStartTime();
            if (ObjectUtil.isNotEmpty(contractStartTime)) {
                int comparison = localDate.compareTo(contractStartTime);
                ZonedDateTime zonedDateTime = contractStartTime.atStartOfDay(ZoneId.systemDefault());
                long startTime = zonedDateTime.toInstant().toEpochMilli();
                if (comparison < 0) {
                    waterMeterReportRequestModel.setQueryBeginTime(startTime);
                }
            }
        }

        log.info("远程调用iot水表明细入参########## {}", JsonUtils.toJsonString(waterMeterReportRequestModel));
        return deviceApi.getWatermeterReport(waterMeterReportRequestModel).getData();
    }

    @Override
    public List<DoorLockInfoVO> getDoorlockInfo() {
        List<DoorLockInfoVO> list = new ArrayList<>();
        Set<Long> roomHouseIdList = doorLockGetRoomId();
        if (CollectionUtil.isEmpty(roomHouseIdList)) {
            return list;
        }
        //过滤合租房间
        List<RoomHouse> roomHouseList = roomHouseRepository.listByIds(roomHouseIdList);
        roomHouseList.forEach(s -> {
            if (!s.getIsWhole()) {
                roomHouseIdList.add(s.getSuperId());
            }
        });
        for (Long roomHouseId : roomHouseIdList) {
            List<RoomSdiotDeviceMapping> roomSdiotDeviceMappings = roomSdiotDeviceMappingService.getDeviceListByRoomId(roomHouseId);
            for (RoomSdiotDeviceMapping roomSdiotDeviceMapping : roomSdiotDeviceMappings) {
                if (DeviceTypeEnum.DOORLOCK.getName().equals(roomSdiotDeviceMapping.getDeviceType())) {
                    String deviceNo = roomSdiotDeviceMapping.getDeviceNo();
                    DoorLockInformation doorLockInformation = deviceApi.getDoorlockInfo(deviceNo).getData();
                    DoorLockInfoVO doorLockInfoVO = new DoorLockInfoVO();
                    doorLockInfoVO.setDeviceNo(deviceNo);
                    doorLockInfoVO.setPower(doorLockInformation.getPower());
                    RoomHouseRespVo roomHouseRespVo = roomHouseService.getRoomHouseinfoById(roomHouseId).getData();
                    doorLockInfoVO.setRoomName(roomHouseRespVo.getFullRoomName());
                    doorLockInfoVO.setStatus(doorLockInformation.getStatus());
                    doorLockInfoVO.setUpdataTime(doorLockInformation.getUpdataTime());
                    list.add(doorLockInfoVO);
                }
            }
        }

        return list;
    }

    @Override
    public List<AddPassword> getPasswordList(String deviceNo, String mobile) {
        return deviceApi.getPasswordList(deviceNo, mobile).getData();
    }

    @Override
    public AddPassword updatePassword(AddPassword addPasswordModel) {
        String deviceNo = addPasswordModel.getDeviceNo();
        ContractTimeVO timeVO = getContractStartAndEndTime(deviceNo);
        if(ObjectUtil.isNotEmpty(timeVO)){
            LocalDate startTime = timeVO.getStartTime();
            LocalDate endTime = timeVO.getEndTime();
            if(startTime !=null){
                long newStartTime = startTime.atStartOfDay().toEpochSecond(ZoneOffset.UTC)* 1000;
                addPasswordModel.setStartTime(newStartTime);
            }
            if(endTime !=null){
                long newEndTime= endTime.atStartOfDay().toEpochSecond(ZoneOffset.UTC)* 1000;
                addPasswordModel.setEndTime(newEndTime);
            }
        }
        RoomSdiotDeviceMapping mapping = roomSdiotDeviceMappingService.getRoomIdByDeviceNo(deviceNo, DeviceTypeEnum.DOORLOCK.getName());
        if (mapping != null) {
            RoomHouse house = roomHouseRepository.getById(mapping.getRoomHouseId());
            if (house != null && !house.getIsWhole() && house.getSuperId() == null) {
                addPasswordModel.setGate(true);
            }
        }
        return deviceApi.updatePassword(addPasswordModel).getData();
    }

    public Set<Long> getRoomId() {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        List<ContractRoomReqVO> list = contractApi.getRoomDataIdByUserId(loginUserId).getData();
        if (CollectionUtil.isNotEmpty(list)) {
            return list.stream()
                    .sorted(Comparator.comparing(ContractRoomReqVO::getStartTime).reversed())   // 根据时间属性降序排序
                    .map(ContractRoomReqVO::getRoomId)  // 提取id属性
                    .collect(Collectors.toSet());
        } else {
            throw new ServiceException(ErrorCodeConstants.CONTRACT_FIND_ROOM_ID.getCode(), ErrorCodeConstants.CONTRACT_FIND_ROOM_ID.getMsg());
        }
    }

    /**
     * 根据member_id查询企业入住、同住人，个人承租人的合同信息
     *
     * @return
     */
    public Set<Long> doorLockGetRoomId() {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        List<ContractRoomReqVO> list = contractApi.getContractByMemberId(loginUserId).getData();
        if (CollectionUtil.isNotEmpty(list)) {
            return list.stream()
                    .sorted(Comparator.comparing(ContractRoomReqVO::getStartTime).reversed())   // 根据时间属性降序排序
                    .map(ContractRoomReqVO::getRoomId)  // 提取id属性
                    .collect(Collectors.toSet());
        } else {
            throw new ServiceException(ErrorCodeConstants.CONTRACT_FIND_ROOM_ID.getCode(), ErrorCodeConstants.CONTRACT_FIND_ROOM_ID.getMsg());
        }
    }

    public ContractTimeVO getContractStartAndEndTime(String deviceNo) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        Set<Long> roomIdList = doorLockGetRoomId();
        for (Long roomHouseId : roomIdList) {
            List<RoomSdiotDeviceMapping> roomSdiotDeviceMappings = roomSdiotDeviceMappingService.getDeviceListByRoomId(roomHouseId);
            for (RoomSdiotDeviceMapping roomSdiotDeviceMapping : roomSdiotDeviceMappings) {
                String deviceNumber = roomSdiotDeviceMapping.getDeviceNo();
                if (deviceNo.equals(deviceNumber)) {
                    long roomHouseId1 = roomSdiotDeviceMapping.getRoomHouseId();
                    List<ContractRoomReqVO> list = contractApi.getRoomDataIdByUserId(loginUserId).getData();
                    for (ContractRoomReqVO contractRoomReqVO : list) {
                        Long roomId = contractRoomReqVO.getRoomId();
                        if (roomHouseId1 == roomId) {
                            LocalDate startTime = contractRoomReqVO.getStartTime();
                            LocalDate endTime = contractRoomReqVO.getEndTime();
                            ContractTimeVO contractTimeVO = new ContractTimeVO();
                            contractTimeVO.setStartTime(startTime);
                            contractTimeVO.setEndTime(endTime);
                        }
                    }

                }
            }
        }
        return null;
    }


}

